package com.vaha.presentation.rest;

import cn.hutool.core.util.IdUtil;
import com.cyber.application.controller.AuthingTokenController;
import com.cyber.domain.constant.HttpResultCode;
import com.cyber.domain.entity.DataResponse;
import com.cyber.domain.entity.IdRequest;
import com.cyber.domain.entity.PagingData;
import com.cyber.domain.entity.Response;
import com.vaha.application.service.TopupPackageService;
import com.vaha.application.service.UserCardBillService;
import com.vaha.application.service.UserCardManifestService;
import com.vaha.application.service.UserCardService;
import com.vaha.domain.entity.TopupPackage;
import com.vaha.domain.entity.UserCard;
import com.vaha.domain.entity.UserCardBill;
import com.vaha.domain.entity.UserCardManifest;
import com.vaha.domain.request.*;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;

@RestController
@RequiredArgsConstructor
public class UserCardRest extends AuthingTokenController {

    private final UserCardService userCardService;

    private final UserCardBillService userCardBillService;

    private final UserCardManifestService userCardManifestService;

    private final TopupPackageService topupPackageService;

    @GetMapping("/user/usercard/search")
    public Response searchUserCard(@Valid UserCardRequest request) {
        DataResponse<PagingData<UserCard>> response = new DataResponse<>();
        UserCard usercard = request.toEvent(getTenantCode());
        PagingData<UserCard> userCardPage = userCardService.selectPage(usercard);
        response.setData(userCardPage);
        return response;
    }


    @GetMapping("/user/usercardbill/search")
    public Response searchUserCardBill(@Valid UserCardBillRequest request) {
        DataResponse<PagingData<UserCardBill>> response = new DataResponse<>();
        UserCardBill usercardbill = request.toEvent(getTenantCode());
        usercardbill.setUserCode(getUser().getString("code"));
        PagingData<UserCardBill> userCardBillPage = userCardBillService.selectPage(usercardbill);
        response.setData(userCardBillPage);
        return response;
    }


    @GetMapping("/user/usercardmanifest/search")
    public Response searchUserCardManifest(@Valid UserCardManifestRequest request) {
        DataResponse<PagingData<UserCardManifest>> response = new DataResponse<>();
        UserCardManifest usercardmanifest = request.toEvent(getTenantCode());
        usercardmanifest.setUserCode(getUser().getString("code"));
        PagingData<UserCardManifest> userCardManifestPage = userCardManifestService.selectPage(usercardmanifest);
        response.setData(userCardManifestPage);
        return response;
    }

    @PutMapping("/user/usercard/topUp")
    public Response topUpUserCard(@RequestBody @Valid TopupRequest request) {
        TopupPackage topupPackage = new TopupPackage();
        topupPackage.setCode(request.getTopUpPackageCode());
        topupPackage = topupPackageService.selectOne(topupPackage);

        if (Objects.isNull(topupPackage)) {
            return Response.fail(HttpResultCode.RECORD_NOT_EXIST);
        }

        UserCard userCoinsCard = new UserCard();
        userCoinsCard.setUserCode(getUser().getString("code"));
        userCoinsCard.setCode("Coins");
        userCoinsCard = userCardService.selectOne(userCoinsCard);

        if (Objects.isNull(userCoinsCard)) {
            return Response.fail(HttpResultCode.RECORD_NOT_EXIST);
        }


        UserCard userBonusesCard = new UserCard();
        userBonusesCard.setUserCode(getUser().getString("code"));
        userBonusesCard.setCode("Bonuses");
        userBonusesCard = userCardService.selectOne(userBonusesCard);

        UserCardManifest userCardManifest = new UserCardManifest();
        userCardManifest.toEvent(userCoinsCard, topupPackage.getId(), 1, getTenantCode());
        userCardManifest.setTransctionName(topupPackage.getCode() + "-" + topupPackage.getName());
        userCardManifest.setToCurrency(topupPackage.getToCurrency());
        userCardManifest.setToAmount(topupPackage.getToAmount());
        userCardManifest.setFromAmount(topupPackage.getFromAmount());
        userCardManifest.setFromCurrency(topupPackage.getFromCurrency());
        userCardManifest.setOpsAmount(topupPackage.getOpsAmount());
        userCardManifest.setOpsCurrency(topupPackage.getOpsCurrency());
        userCardManifest.setOpsCardCode(userBonusesCard.getCode());
        userCardManifest.setTransctionSummary(String.format("Self Top-Up，Pay %s get coins",topupPackage.getFromAmount()));
        userCardManifestService.save(userCardManifest);

        BigDecimal balanceCoins = userCoinsCard.getBalance();
        balanceCoins = balanceCoins.add(topupPackage.getToAmount());
        userCoinsCard.setBalance(balanceCoins);

        BigDecimal balanceBonuses = userBonusesCard.getBalance();
        balanceBonuses = balanceBonuses.add(topupPackage.getOpsAmount());
        userBonusesCard.setBalance(balanceBonuses);

        userCardService.updateById(userCoinsCard);
        userCardService.updateById(userBonusesCard);
        return Response.success();
    }

    @GetMapping("/admin/usercard/search")
    public Response searchAdminUserCard(@Valid UserCardRequest request) {
        DataResponse<PagingData<UserCard>> response = new DataResponse<>();
        UserCard usercard = request.toEvent(getTenantCode());
        PagingData<UserCard> userCardPage = userCardService.selectPage(usercard);
        response.setData(userCardPage);
        return response;
    }


    @GetMapping("/admin/usercard")
    public Response selectOneUserCard(@Valid IdRequest idRequest) {
        DataResponse<UserCard> response = new DataResponse<>();

        UserCard userCard = new UserCard();
        userCard.setId(idRequest.getId());
        userCard.setTenantCode(getTenantCode());
        userCard = userCardService.selectOne(userCard);

        response.setData(userCard);
        return response;
    }

    @PostMapping("/admin/usercard")
    public Response saveUserCard(@RequestBody @Valid CreateUserCardRequest request) {
        UserCard usercard = request.toEvent(getSessionId(), getTenantCode());

        int result = userCardService.save(usercard);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @PutMapping("/admin/usercard")
    public Response updateUserCard(@RequestBody @Valid UpdateUserCardRequest request) {
        UserCard usercard = request.toEvent(getSessionId(), getTenantCode());
        int result = userCardService.updateById(usercard);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @DeleteMapping("/admin/usercard")
    public Response deleteUserCard(@Valid IdRequest idRequest) {
        UserCard userCard = new UserCard();
        userCard.setId(idRequest.getId());

        userCard.setTenantCode(getTenantCode());
        userCard.setUpdator(getSessionId());
        userCard.setUpdateTime(new Date());

        int result = userCardService.deleteById(userCard);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @GetMapping("/admin/usercardbill/search")
    public Response searchAdminUserCardBill(@Valid UserCardBillRequest request) {
        DataResponse<PagingData<UserCardBill>> response = new DataResponse<>();
        UserCardBill usercardbill = request.toEvent(getTenantCode());
        PagingData<UserCardBill> userCardBillPage = userCardBillService.selectPage(usercardbill);
        response.setData(userCardBillPage);
        return response;
    }


    @GetMapping("/admin/usercardbill")
    public Response selectOneUserCardBill(@Valid IdRequest idRequest) {
        DataResponse<UserCardBill> response = new DataResponse<>();

        UserCardBill userCardBill = new UserCardBill();
        userCardBill.setId(idRequest.getId());
        userCardBill.setTenantCode(getTenantCode());
        userCardBill = userCardBillService.selectOne(userCardBill);

        response.setData(userCardBill);
        return response;
    }

    @PostMapping("/admin/usercardbill")
    public Response saveUserCardBill(@RequestBody @Valid CreateUserCardBillRequest request) {
        UserCardBill usercardbill = request.toEvent(getSessionId(), getTenantCode());

        int result = userCardBillService.save(usercardbill);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @PutMapping("/admin/usercardbill")
    public Response updateUserCardBill(@RequestBody @Valid UpdateUserCardBillRequest request) {
        UserCardBill usercardbill = request.toEvent(getSessionId(), getTenantCode());
        int result = userCardBillService.updateById(usercardbill);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @DeleteMapping("/admin/usercardbill")
    public Response deleteUserCardBill(@Valid IdRequest idRequest) {
        UserCardBill userCardBill = new UserCardBill();
        userCardBill.setId(idRequest.getId());

        userCardBill.setTenantCode(getTenantCode());
        userCardBill.setUpdator(getSessionId());
        userCardBill.setUpdateTime(new Date());

        int result = userCardBillService.deleteById(userCardBill);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @GetMapping("/admin/usercardmanifest/search")
    public Response searchAdminUserCardManifest(@Valid UserCardManifestRequest request) {
        DataResponse<PagingData<UserCardManifest>> response = new DataResponse<>();
        UserCardManifest usercardmanifest = request.toEvent(getTenantCode());
        PagingData<UserCardManifest> userCardManifestPage = userCardManifestService.selectPage(usercardmanifest);
        response.setData(userCardManifestPage);
        return response;
    }


    @GetMapping("/admin/usercardmanifest")
    public Response selectOneUserCardManifest(@Valid IdRequest idRequest) {
        DataResponse<UserCardManifest> response = new DataResponse<>();

        UserCardManifest userCardManifest = new UserCardManifest();
        userCardManifest.setId(idRequest.getId());
        userCardManifest.setTenantCode(getTenantCode());
        userCardManifest = userCardManifestService.selectOne(userCardManifest);

        response.setData(userCardManifest);
        return response;
    }

    @PostMapping("/admin/usercardmanifest")
    public Response saveUserCardManifest(@RequestBody @Valid CreateUserCardManifestRequest request) {
        UserCardManifest usercardmanifest = request.toEvent(getSessionId(), getTenantCode());

        int result = userCardManifestService.save(usercardmanifest);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @PutMapping("/admin/usercardmanifest")
    public Response updateUserCardManifest(@RequestBody @Valid UpdateUserCardManifestRequest request) {
        UserCardManifest usercardmanifest = request.toEvent(getSessionId(), getTenantCode());
        int result = userCardManifestService.updateById(usercardmanifest);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @DeleteMapping("/admin/usercardmanifest")
    public Response deleteUserCardManifest(@Valid IdRequest idRequest) {
        UserCardManifest userCardManifest = new UserCardManifest();
        userCardManifest.setId(idRequest.getId());

        userCardManifest.setTenantCode(getTenantCode());
        userCardManifest.setUpdator(getSessionId());
        userCardManifest.setUpdateTime(new Date());

        int result = userCardManifestService.deleteById(userCardManifest);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }
}
